package com.easyaccount.service;

import com.easyaccount.bean.MenuTree;
import com.easyaccount.bean.RoleMenuTree;
import com.easyaccount.commons.CommonResp;
import com.easyaccount.commons.TablePage;
import com.easyaccount.dao.MenuMapper;
import com.easyaccount.dao.RoleMapper;
import com.easyaccount.dao.RoleMenuMapper;
import com.easyaccount.exception.BizException;
import com.easyaccount.model.Menu;
import com.easyaccount.model.Role;
import com.easyaccount.model.RoleMenu;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

@Service
public class RoleService {
    @Resource
    private RoleMapper roleMapper;
    @Resource
    private RoleMenuMapper roleMenuMapper;
    @Resource
    private MenuService menuService;
    @Resource
    private MenuMapper menuMapper;

    @Transactional(rollbackFor = Exception.class)
    public CommonResp save(Role role,List<Integer> selectedMenuIds){
        int count = roleMapper.selectByIdAndNameCount(role);
        if (count > 0) throw new BizException("角色名已存在",444);

        roleMapper.insertSelective(role);
        List<RoleMenu> list = new ArrayList<>();
        for (Integer selectedMenuId : selectedMenuIds) {
            RoleMenu roleMenu = new RoleMenu();
            roleMenu.setRoleId(role.getRoleId());
            roleMenu.setMenuId(selectedMenuId);
            list.add(roleMenu);
        }
        roleMenuMapper.insertBatch(list);
        return CommonResp.success();
    }

    public TablePage searchByName(TablePage tablePage, String roleName){
        int size = tablePage.getLimit();
        int start = (tablePage.getPage() - 1) * size;

        List<Role> roles = roleMapper.selectByName(start, size, roleName);

        int count = roleMapper.selectByNameCount(roleName);
        tablePage.setCount(count);
        tablePage.setData(roles);
        return tablePage;
    }

    @Transactional(rollbackFor = Exception.class)
    public CommonResp update(Role role,List<Integer> selectedMenuIds){
        if(role.getRoleId() == 1) throw new BizException("不允许修改管理员角色",444);

        int count = roleMapper.selectByIdAndNameCount(role);
        if (count > 0) throw new BizException("角色名已存在",444);

        List<RoleMenu> roleMenus = roleMenuMapper.selectByRoleId(role.getRoleId());
        List<Integer> toDels = new ArrayList<>();
        for (RoleMenu roleMenu : roleMenus) {
            toDels.add(roleMenu.getMenuId());
        }
        toDels.removeAll(selectedMenuIds); // toDels中剩下的就是要删除的

        List<Integer> temps = new ArrayList<>();
        for (RoleMenu roleMenu : roleMenus) {
            temps.add(roleMenu.getMenuId());
        }
        selectedMenuIds.removeAll(temps); // selectedMenuIds中剩下的就是要增加的
        List<RoleMenu> adds = new ArrayList<>();
        for (Integer selectedMenuId : selectedMenuIds) {
            RoleMenu roleMenu = new RoleMenu();
            roleMenu.setRoleId(role.getRoleId());
            roleMenu.setMenuId(selectedMenuId);
            adds.add(roleMenu);
        }
        if (adds.size() > 0){
            int i = roleMenuMapper.insertBatch(adds);
            if (i < 1) throw new BizException("修改失败",444);
        }
        if (toDels.size() > 0){
            int k = roleMenuMapper.deleteBatch(role.getRoleId(), toDels);
            if (k < 0)  throw new BizException("修改失败",444);
        }

        int n = roleMapper.updateByPrimaryKeySelective(role);
        if (n < 1)  throw new BizException("修改失败",444);

        return CommonResp.success();
    }


    public CommonResp delete(Role role){
        Role result = roleMapper.selectByPrimaryKey(role.getRoleId());
        if(result == null) throw new BizException("角色不存在",444);
        if(result.getRoleId() == 1) throw new BizException("不允许删除管理员角色",444);

        int i = roleMapper.deleteByPrimaryKey(role.getRoleId());
        if (i == 0) throw new BizException("删除失败",444);

        roleMenuMapper.deleteByRoleId(role.getRoleId());
        return CommonResp.success();
    }

    public CommonResp list(){
        List<Role> depts = roleMapper.selectAll();
        return CommonResp.success(depts);
    }
    public CommonResp roleMenuLists(Integer roleId){
        Map<String,Object> map = new HashMap<>();
        List<RoleMenuTree> roleMenuTrees = toTree();
        map.put("menus",roleMenuTrees);

        if(roleId != null){
            map.put("selected",getRoleMenuIds(roleId));
        }
        return CommonResp.success(map);
    }

    public List<RoleMenuTree> toTree(){
        List<Menu> menus = menuService.getMenuAll();

        List<RoleMenuTree> trees = new ArrayList<>();
        for (Menu menu : menus) {
            Integer parentId = menu.getParentId();
            if(parentId == 0){
                RoleMenuTree roleMenuTree = new RoleMenuTree();
                roleMenuTree.setChildren(new ArrayList<>());
                roleMenuTree.setId(menu.getMenuId());
                roleMenuTree.setTitle(menu.getMenuName());
                roleMenuTree.setOrderNum(menu.getOrderNum());
                trees.add(roleMenuTree);
            }
        }

        if(trees.size() > 1) {
            // 排序
            trees.sort(new Comparator<RoleMenuTree>() {
                @Override
                public int compare(RoleMenuTree o1, RoleMenuTree o2) {
                    return o1.getOrderNum() - o2.getOrderNum();
                }
            });
        }
        create(trees,menus);

        return trees;
    }

    private void create(List<RoleMenuTree> root, List<Menu> menus){
        for (RoleMenuTree roleMenuTree : root) {
            Integer menuId = roleMenuTree.getId();
            List<RoleMenuTree> childrens = roleMenuTree.getChildren();

            for (Menu menu : menus) {
                Integer parentId = menu.getParentId();
                if(menuId == parentId) {
                    RoleMenuTree mt = new RoleMenuTree();
                    mt.setChildren(new ArrayList<>());
                    mt.setId(menu.getMenuId());
                    mt.setTitle(menu.getMenuName());
                    mt.setOrderNum(menu.getOrderNum());
                    childrens.add(mt);
                }
            }

            // 排序
            if (childrens != null && childrens.size() > 1) {
                childrens.sort(new Comparator<RoleMenuTree>() {
                    @Override
                    public int compare(RoleMenuTree o1, RoleMenuTree o2) {
                        return o1.getOrderNum() - o2.getOrderNum();
                    }
                });

                create(childrens,menus);
            }

        }
    }

    private List<Integer> getRoleMenuIds(int roleId){
        List<RoleMenu> roleMenus = roleMenuMapper.selectByRoleId(roleId);
        List<Integer> menuIds = new ArrayList<>();
        roleMenus.forEach(roleMenu -> {
            menuIds.add(roleMenu.getMenuId());
        });
        List<Menu> menus = menuMapper.selectByPrimaryKeys(menuIds);
        List<MenuTree> trees = menuService.toTree(menus);

        List<Integer> reslut = new ArrayList<>();
        f(reslut,trees);
        return reslut;
    }

    private void f(List<Integer> reslut,List<MenuTree> chd){
        for (MenuTree tree : chd) {
            Integer menuId = tree.getMenuId();
            List<MenuTree> childrens = tree.getChildrens();
            if(childrens.size() > 0){
                f(reslut,childrens);
            }else{
                reslut.add(menuId);
            }
        }
    }
}
